#include "dominion.h"
#include "dominion_helpers.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "rngs.h"
#include "helper.h"
#include <math.h>
#include <unistd.h>


int playPriority[10];
int buyPriority[14];
int actionCounter;
int gameCounter;

// plays a random game


// prints game state to stderr
int printState(struct gameState *state, int player){
    fprintf(stderr, "State in game %d at action %d\n", gameCounter, actionCounter);
    fprintf(stderr, "Player: %d\n", state->whoseTurn);
    fprintf(stderr, "Phase: %d\n" , state->phase);
    fprintf(stderr, "Actions: %d\n", state->numActions);
    fprintf(stderr, "Coins: %d\n", state->coins);
    fprintf(stderr, "Buys: %d\n", state->numBuys);
    fprintf(stderr, "Hand Count: %d\n", state->handCount[state->whoseTurn]);
    fprintf(stderr, "Deck Count: %d\n", state->deckCount[state->whoseTurn]);
    fprintf(stderr, "Discard Count: %d\n", state->discardCount[state->whoseTurn]);
    fprintf(stderr, "Played Count: %d\n", state->playedCardCount);
    return 0;
}

// builds the priority lists for the randomly generated kingdom cards to cover all combinations
int buildPriorities(int cards[]){
    int i;
    int j;
    int newCards[14];
    int counter = 0;
    int origPlayPriorities[19] = {
    tribute, village, great_hall, minion, steward,
    council_room, cutpurse, embargo, outpost,
    adventurer, feast, mine, remodel, smithy,
    baron, ambassador, salvager, sea_hag, treasure_map
    }; // tries to play action cards first
    int origBuyPriorities[24] = {
    province, tribute, gold, village, great_hall,
    minion, steward, cutpurse, silver, embargo,
    outpost, council_room, gardens, feast, adventurer,
    mine, remodel, smithy, baron, ambassador, salvager,
    sea_hag, treasure_map, duchy
    }; // tries to buy high priority play cards first
    // builds play priorities
    for (i = 0; i < 19; i++){
        for (j = 0; j < 10; j++){
            if (origPlayPriorities[i] == cards[j]){
                playPriority[counter] = origPlayPriorities[i];
                counter++;
            }
        }
    }
    // builds buy priorities
    for (i = 0; i < 10; i++){
        newCards[i] = cards[i];
    }
    // adds in non-kingdom cards that are important to buy
    newCards[10] = gold;
    newCards[11] = silver;
    newCards[12] = duchy;
    newCards[13] = province;

    counter = 0;
    for (i = 0; i < 24; i++){
        for (j = 0; j < 14; j++){
            if (origBuyPriorities[i] == newCards[j]){
                buyPriority[counter] = origBuyPriorities[i];
                counter++;
            }
        }
    }
    return 0;
}

// AI logic to handle playing all available cards.  Most of this logic is just shortcuts and would need to be
// improved significantly to make a competitive AI.
int playSelectedCard(int handPos, int playerPlayCard, int player, struct gameState *state){
    int counter;
    int counter2;
    int counter3;
    int i;
    switch(playerPlayCard){
        case 7:
            // adventurer
            playCard(handPos, 0, 0, 0, state);
            break;
        case 8:
            //council_room
            playCard(handPos, 0, 0, 0, state);
            break;
        case 9:
            //feast
            counter = -1;
            for (i = 0; i < 14; i++){
                if (getCost(buyPriority[i]) <= 5)
                    counter = buyPriority[i];
            }
            if (counter >= 0)
                playCard(handPos, counter, 0, 0, state);
            else
                return -1;
            break;
        case 11:
            //mine
            counter = -1;
            counter2 = -1;
            for (i = 0; i < state->handCount[player]; i++){
                if (state->hand[player][i] == copper  && state->hand[player][counter] != silver){
                    counter = i;
                    counter2 = silver;
                }
                else if (state->hand[player][i] == silver){
                    counter = i;
                    counter2 = gold;
                }
            }
            if (counter >= 0){
                playCard(handPos, counter, counter2, 0, state);
            }
            else
                return -1;
            break;
        case 12:
            //remodel
            counter = 0;
            counter2 = -1;
            counter3 = -1;
            for (i = state->handCount[player]; i >= 0; i--){
                if (counter < getCost(state->hand[player][i])){
                    counter = getCost(state->hand[player][i]);
                    counter2= i;
                }
            }
            for (i = 0; i < 24; i++){
                if (counter2 < getCost(buyPriority[i]))
                    counter3 = buyPriority[i];
            }

            playCard(handPos, counter, counter3, 0, state);
            break;
        case 13:
            //smithy
            playCard(handPos, 0, 0, 0, state);
            break;
        case 14:
            //village
            playCard(handPos, 0, 0, 0, state);
            break;
        case 15:
            //baron
            counter = 0;
            counter2 = 0;
            for (i = 0; i < state->handCount[player]; i++){
                if (state->hand[player][i] == estate){
                    counter++;
                    counter2 = i;
                }
            }
            if (counter > 0){
                playCard(handPos, 1, counter2, 0, state);
            }
            else
                playCard(handPos, 0, 0, 0, state);
            break;
        case 16:
            //great_hall
            playCard(handPos, 0, 0, 0, state);
            break;
        case 17:
            //minion
            playCard(handPos, 1, 0, 0, state);
            break;
        case 18:
            //steward
            playCard(handPos, 1, 0, 0, state);
            break;
        case 19:
            //tribute
            playCard(handPos, 0, 0, 0, state);
            break;
        case 20:
            //ambassador
            counter = 0;
            counter2 = -1;
            counter3 = -1;
            for (i = 0; i < state->handCount[player]; i++){
                if (state->hand[player][i] == copper){
                    counter++;
                    if (counter2 == -1)
                        counter2 = i;
                    else
                        counter3 = i;
                }
            }
            if (counter > 2)
                counter = 2;
            if (counter > 0){
                playCard(handPos, counter2, counter, 0, state);
            }
            else
                playCard(handPos, 0, 1, 0, state);
            break;
        case 21:
            //cutpurse
            playCard(handPos, 0, 0, 0, state);
            break;
        case 22:
            //embargo
            playCard(handPos, state->hand[player][0], 0, 0, state);
            break;
        case 23:
            //outpost
            playCard(handPos, 0, 0, 0, state);
            break;
        case 24:
            //salvager
            counter = 0;
            counter2 = -1;
            for (i = state->handCount[player]; i >= 0; i--){
                if (counter < getCost(state->hand[player][i])){
                    counter = getCost(state->hand[player][i]);
                    counter2= i;
                }
            }
            playCard(handPos, counter2, 0, 0, state);
            break;
        case 25:
            //sea_hag
            playCard(handPos, 0, 0, 0, state);
            break;
        case 26:
            //treasure_map
            counter = 0;
            for (i = 0; i < state->handCount[player]; i++){
                if (state->hand[player][i] == treasure_map)
                    counter++;
            }
            if (counter >= 2){
                playCard(handPos, 0, 0, 0, state);
            }
            break;
        default:
            printf("Error playing card %s\n", cardToString(playCard));
            return -1;
            break;
}
    printf("Playing %s\n", cardToString(playCard));
    return 0;
}

// handles the player's turn, playing then buying.
int playerTurn(int player, struct gameState *state){
    int i;
    int j;
    int handPos = -1;
    int playerPlayCard= -1;
    int playerBuyCard = -1;

    // decides what to play
    while (state->numActions > 0){
        for (i = 0; i < state->handCount[player]; i++){
            printf("Looking at: %s \n", cardToString(state->hand[player][i]));
            for (j=0; j < 14; j++){
                if (handPos == 0 && state->hand[player][i] == playPriority[j]){
                    handPos = i;
                   playerPlayCard= state->hand[player][i];
                }
            }
        }
        if (handPos == -1 ||playerPlayCard== -1)
            break;
        else{
            printf("Playing %s\n", cardToString(playCard));
            printState(state, player);
            printf("play loop\n");
            playSelectedCard(handPos, playCard, player, state);
            actionCounter++;
        }
        handPos = -1;
       playerPlayCard= -1;
    }
    printState(state, player);

    // decides what to buy
    while (state->numBuys > 0){
        for (i = 0; i < 14; i++){
            if ( state->coins >= getCost(buyPriority[i]) && playerBuyCard == -1 && state->supplyCount[buyPriority[i]] > 0){
                playerBuyCard = buyPriority[i];
                printf("buy priority: %s cost is %d\n", cardToString(buyPriority[i]) , getCost(buyPriority[i]));
            }
        }
        if (playerBuyCard != -1){
            printf("Buying %s\n", cardToString(playerBuyCard));
            printState(state, player);
            buyCard(playerBuyCard, state);
            actionCounter++;
        }
        else
            break;
        playerBuyCard = -1;
    }
    return 0;
}



int main(int argc, char** argv){
    int err;
    int out;
    int numPlayers;
    int randomSeed = 0;
    struct gameState *state = malloc(sizeof(struct gameState));
    int cards[10];
    int cardCount = 0;
    int testCard;
    int i = 0;
    int curPlayer = 0;
    int t;
    int numTests = 100;
    actionCounter = 0;  // used to help sync the two files
    gameCounter = 0;    // counts game number

    for (t =0; t < numTests; t++){
    gameCounter++;
    randomSeed = t * 10 + 1;
    fprintf(stderr, "Starting test with random seed %d\n", randomSeed);
    cardCount = 0;


    // builds random kingdom card list
    while(cardCount < 10){
        testCard = floor(Random() * (treasure_map - adventurer)) + adventurer;
        if (cardCount == 0){
            cards[0] = testCard;
            cardCount++;

        }
        else{
            for (i = 0; i <= cardCount; i++){
                if (cards[i] == testCard){
                    break;
                }
                else if (i == cardCount){
                    cards[i] = testCard;
                    cardCount++;
                    break;
                }
            }
        }
    }

    // sets number of players
    numPlayers = floor(Random() * 2) + 2;
    curPlayer = 0;

    initializeGame(numPlayers, cards, randomSeed, state);
    printf("Game is initialized with %d players\n", numPlayers);

    // displays kingdom cards
    printf("Kingdom Cards in play: ");
    for (i = 0; i < 10; i++){
        printf(" %s ", cardToString(cards[i]));
        printf(" %d ", cards[i]);
    }
    printf("\n");
    buildPriorities(cards);

    // displays priorities
    printf("Play Priority of cards in play: ");
    for (i = 0; i < 10; i++){
        printf(" %s ", cardToString(playPriority[i]));
    }
    printf("\n");

    printf("Buy Priority of cards in play: ");
    for (i = 0; i < 14; i++){
        printf(" %s ", cardToString(buyPriority[i]));
    }
    printf("\n");

    // main game loop
   while (!isGameOver(state)){
        printf("Player %d turn starts\n", curPlayer);
        printf("Action Counter: %d\n", actionCounter);
        shuffle(curPlayer, state);
        printState(state, curPlayer);
        playerTurn(curPlayer, state);
        printState(state, curPlayer);
        endTurn(state);
        printState(state, curPlayer);
        printf("Player %d turn ends.\n", curPlayer);
        curPlayer = whoseTurn(state);
    }

    printf("Calculating Scores\n");

    for (i = 0; i < numPlayers; i++){
        printf("Player %d score: %d\n", i, scoreFor(i, state));
    }
}

    free(state);
    return 0;
}
